package dashboard

import (
	model "aggregation/model/dashboard"
	"aggregation/store"
	"aggregation/store/postgres"
	"aggregation/store/redis"
	"context"
	"time"
)

type device struct {
	Unbind             store.ICounter
	Bind               store.ICounter
	Bind4G             store.ICounter
	BindBluetooth      store.ICounter
	Lost               store.ICounter
	Fault              store.ICounter
	RideDistance       store.ICounter
	UnbindCache        store.ICache
	BindCache          store.ICache
	Bind4GCache        store.ICache
	BindBluetoothCache store.ICache
	LostCache          store.ICache
	FaultCache         store.ICache
	RideDistanceCache  store.ICache
}

var Device = &device{
	Unbind:             postgres.Unbind,
	Bind:               postgres.Bind,
	Bind4G:             postgres.Bind4G,
	BindBluetooth:      postgres.BindBluetooth,
	Lost:               postgres.Lost,
	Fault:              postgres.Fault,
	RideDistance:       postgres.RideDisntance,
	UnbindCache:        redis.UnbindCache,
	BindCache:          redis.BindCache,
	Bind4GCache:        redis.Bind4GCache,
	BindBluetoothCache: redis.BindBluetoothCache,
	LostCache:          redis.LostCache,
	FaultCache:         redis.FaultCache,
	RideDistanceCache:  redis.RideDistanceCache,
}

func (d *device) DeviceBoard(ctx context.Context) (model.DeviceBoardResponse, error) {
	var (
		board model.DeviceBoardResponse
	)

	bindBike, _ := d.Bind.Count(ctx)
	bindBike4G, _ := d.Bind4G.Count(ctx)
	bindBikeBluetooth, _ := d.BindBluetooth.Count(ctx)
	distance, _ := d.RideDistance.Count(ctx)
	now := time.Now()
	// 昨日新增
	day := dayIncrease(ctx, now.AddDate(0, 0, -1), d.BindCache, d.Bind)
	// 本月新增
	month := monthIncrease(ctx, now, d.BindCache, d.Bind)
	// 今年新增
	year := yearIncrease(ctx, now, d.BindCache, d.Bind)
	board = model.DeviceBoardResponse{
		BindBike:      bindBike,
		FourGBike:     bindBike4G,
		BluetoothBike: bindBikeBluetooth,
		Distance:      float64(distance) / 1000.0,
		Day:           day,
		Month:         month,
		Year:          year,
	}
	return board, nil
}

func (d *device) DeviceBindWave(ctx context.Context, period model.PERIOD) (model.DeviceBindWaveResponse, error) {
	var (
		wave model.DeviceBindWaveResponse
		err  error
	)
	if period == "" {
		period = model.DAY
	}
	wave.Period = period

	switch period {
	case model.MONTH:
		wave.FourG = monthWave(ctx, time.Now(), d.Bind4GCache, d.Bind4G)
		wave.Bluetooth = monthWave(ctx, time.Now(), d.BindBluetoothCache, d.BindBluetooth)
	case model.YEAR:
		wave.FourG = yearWave(ctx, d.Bind4GCache, d.Bind4G)
		wave.Bluetooth = yearWave(ctx, d.BindBluetoothCache, d.BindBluetooth)
	default:
		wave.FourG = dayWave(ctx, time.Now(), d.Bind4GCache, d.Bind4G)
		wave.Bluetooth = dayWave(ctx, time.Now(), d.BindBluetoothCache, d.BindBluetooth)
	}
	return wave, err
}

func (d *device) DeviceLostBoard(ctx context.Context) (model.DeviceLostBoardResponse, error) {
	var (
		board model.DeviceLostBoardResponse
	)
	total, _ := d.Lost.Count(ctx)
	now := time.Now()
	day := dayIncrease(ctx, now.AddDate(0, 0, -1), d.LostCache, d.Lost)
	// 本月新增
	month := monthIncrease(ctx, now, d.LostCache, d.Lost)
	// 今年新增
	year := yearIncrease(ctx, now, d.LostCache, d.Lost)
	board = model.DeviceLostBoardResponse{
		Lost:  total,
		Day:   day,
		Month: month,
		Year:  year,
	}
	return board, nil
}

func (d *device) DeviceLostWave(ctx context.Context, period model.PERIOD) (model.DeviceLostWaveResponse, error) {
	var (
		wave model.DeviceLostWaveResponse
	)
	if period == "" {
		period = model.DAY
	}
	wave.Period = period
	switch period {
	case model.MONTH:
		wave.LostBike = monthWave(ctx, time.Now(), d.LostCache, d.Lost)
	case model.YEAR:
		wave.LostBike = yearWave(ctx, d.LostCache, d.Lost)
	default:
		wave.LostBike = dayWave(ctx, time.Now(), d.LostCache, d.Lost)
	}
	return wave, nil
}

func (d *device) DeviceFaultBoard(ctx context.Context) (model.DeviceFaultBoardResponse, error) {
	var (
		board model.DeviceFaultBoardResponse
	)
	total, _ := d.Fault.Count(ctx)
	now := time.Now()
	day := dayIncrease(ctx, now.AddDate(0, 0, -1), d.FaultCache, d.Fault)
	// 本月新增
	month := monthIncrease(ctx, now, d.FaultCache, d.Fault)
	// 今年新增
	year := yearIncrease(ctx, now, d.FaultCache, d.Fault)
	board = model.DeviceFaultBoardResponse{
		Fault: total,
		Day:   day,
		Month: month,
		Year:  year,
	}
	return board, nil
}

func (d *device) DeviceFaultWave(ctx context.Context, period model.PERIOD) (model.DeviceFaultWaveResponse, error) {
	var (
		wave model.DeviceFaultWaveResponse
	)
	if period == "" {
		period = model.DAY
	}
	wave.Period = period
	switch period {
	case model.MONTH:
		wave.Fault = monthWave(ctx, time.Now(), d.FaultCache, d.Fault)
	case model.YEAR:
		wave.Fault = yearWave(ctx, d.FaultCache, d.Fault)
	default:
		wave.Fault = dayWave(ctx, time.Now(), d.FaultCache, d.Fault)
	}
	return wave, nil
}

// DeviceSummary 后台统计页面 车辆统计
// 主要返回车辆总数/绑定车辆数据
func (d *device) DeviceSummary(ctx context.Context) model.DeviceSummaryResponse {
	var resp model.DeviceSummaryResponse
	bind, _ := d.Bind.Count(ctx)
	unbind, _ := d.Unbind.Count(ctx)
	resp.Total = bind + unbind
	resp.Bind = bind
	return resp
}
